<?php
/**
 * Created on 7 mai 2011
 * * @author Samy Deghou(deghou@polytech.unice.fr ; deghou@embl.de)
 * 		   Stephan Beisken (beisken@ebi.ac.uk)
 * 		   Luis Felipe De Figueiredo (ldpf@ebi.ac.uk)
 * To change the template for this generated file go to
 * Window - Preferences - PHPeclipse - PHP - Code Templates
 */
class cmlspecParser{
	
	private $_cmlFile=null;
	
	public function cmlspecParser($fileName){
		$this->_cmlFile="/var/www/luiskein-tool/luiskein-tool/trunk/main/webappTest/cmlData/".$fileName;
	}
	
	public function parseDocument(){
	
	/*
	 * For efficiency
	 */
	$ArrayOfAtoms=array(); $ArrayOfBonds=array(); $ArrayOfPeaks=array();$ArrayOfMolecules=array();$ArrayOfCS2D=array();$ArrayOfBondAtom=array();
	$_currentObject_ATOM; $_currentObject_BOND; $_currentObject_PEAK; $_currentObject_MOLECULE;
	$_currentObject_CS2D;
	$_mapAtomId; $_mapBondId; $_mapMoleculeId;$_mapPeakId;
	
    /*
     * Attributes that need to be found in order to feel the table ATOM
     */
     $_ATOM_symbol; $_ATOM_is_aromatic=0; $_ATOM_is_visible=0; $_ATOM_formal_charge; $_ATOM_atomic_mass=0; $_ATOM_signature=0;
     $atomId;$atomX;$atomY;$atomHydrogenCount;
    /*
     * Attributes that need to be found in order to feel the table PEAK
     */
	$peakId; $xValue; $multiplicity; $height; $atomRefs; $peakShape; $maxPValue=0; $molRefs; $xUnits; $yUnits;
    /*
     * Attributes that need to be found in order to feel the table BOND
     */
     $_BOND_degree=0; $_BOND_stereo=0; $_BOND_is_config_spec=0;
     $bondId; $type; $source; $target;
	/*
	 * Attributes that need to be found in order to feel the table MOLECULE
	 */
	 $_MOLECULE_chebi_id="null"; $_MOLECULE_date=getdate(); $_MOLECULE_exact_mass ; 
	 $_MOLECULE_inchi ; $_MOLECULE_inchi_key ; $_MOLECULE_name ; $_MOLECULE_fingerprint="null";
	
	
	$mol="";
		
	//Loading extern file
	$srcFile = new DOMDocument('1->0', 'utf-8');
	$srcFile->formatOutput = true;
	$srcFile->preserveWhiteSpace = false;
	$srcFile->load($this->_cmlFile);
	$component=$srcFile->getElementsByTagName('metadataList');
		
	$experimentType=$srcFile->getElementsByTagName("metadataList")->item(0)->childNodes->item(1)->attributes->item(0)->value;
//	var_dump("we are dealing with an experiment of type: ".$experimentType."</br>"."</br>");
	$THEMOLECULENAME="";$THEMOLECULEID="";
	if(cmlspecParser::startsWith("ms",$experimentType)){
		$experimentType="ms";
		$THEMOLECULENAME=$srcFile->getElementsByTagName("reactant")->item(0)->childNodes->item(0)->attributes->item(0)->value;
	}else if(cmlspecParser::startsWith("nmr",experimentType)){
		$experimentType="nmr";
		$THEMOLECULENAME=$srcFile->getElementsByTagName('molecule')->item(0)->attributes->item(0)->value;
		$THEMOLECULEID=$srcFile->getElementsByTagName('molecule')->item(0)->attributes->item(1)->value;
	}

	$molecules=$srcFile->getElementsByTagName("moleculeList");
	if($experimentType=="ms"){
		if($molecules->length!=0){//Stephen files: moleculeList is the tag holding all the information about the molecules
			$listOfMolecules=$molecules->item(0)->childNodes;			
		}else{//2008 cml files: moleculeList does not exist-> INstead, we have productList
			$listOfMolecules=$srcFile->getElementsByTagName('cml:molecule');
		}
	}else{
//		$listOfMolecules[0]=$srcFile->getElementsByTagName("molecule");
	}
	foreach($listOfMolecules as $molecule){
		if($molecule instanceof DOMElement){
//			$atom=$molecule->childNodes->item(1)->childNodes;
//			var_dump($atom->length);
		}
	}
	

	foreach($listOfMolecules as $molecule){
		$MS = $molecule instanceof DOMElement;
		$NMR = $molecule instanceof DOMHTMLCollection;
		$moleculeName;
		$moleculeNode;
		if($MS){
			$moleculeNode=$molecule;
		}else if($NMR){
			$$moleculeNode=$molecule[0];
		}
		if($MS || $NMR){
			if($MS){
				$moleculeName=$moleculeNode->attributes->item(0)->value;
				$_MOLECULE_name=$moleculeName;
			//	echo("new molecule :  ".$moleculeName.".   ");
			}else if($NMR){
				$moleculeName=THEMOLECULENAME;
			}
			$atomArray=$moleculeNode->childNodes->item(0)->childNodes;
			$bondArray=$moleculeNode->childNodes->item(1)->childNodes;	
			$scalarInformation=$moleculeNode->getElementsByTagName("scalar");
			/*
			 * Atoms
			 */
			foreach($atomArray as $atome){
				for($k=0;$k<$atome->attributes->length;$k++){
					$attribute=$atome->attributes->item($k);
					$attributeName=$attribute->name;
					$attributeValue=$attribute->value;
					switch($attributeName){
					case "id":
						$atomId=$attributeValue;
						break;
					case "elementType":
						$_ATOM_symbol=$attributeValue;
						break;
					case "x2":
						$atomX=floatval($attributeValue);
						break;
					case "y2":
						$atomY=floatval($attributeValue);
						break;
					case "formalCharge":
						$_ATOM_formal_charge=$attributeValue;
						break;
					case "hydrogenCount":
						$atomHydrogenCount=$attributeValue;
						break;
					case "isotopeNumber":
						$_ATOM_atomic_mass=$attributeValue;
						break;
					}
				}
				$_currentObject_ATOM=new Atom($atomId, $_ATOM_symbol, $_ATOM_is_aromatic, $_ATOM_is_visible, $_ATOM_formal_charge,
				    						  $_ATOM_atomic_mass, $_ATOM_signature);
				 array_push($ArrayOfAtoms,$_currentObject_ATOM);
				 $mapOfCoordinates[$atomId]=array($atomX,$atomY);
			}
			/*
			 * The bonds
			 */
			for($k=0;$k<$bondArray->length;$k++){
				$bond=$bondArray->item($k);
				$tag=$bond->nodeName;
				$isThereAStereoForThisBond=$bond->childNodes->length;
				if($isThereAStereoForThisBond!=0 && $bond->childNodes->item(0)->nodeName=="bondStereo"){
					$_BOND_stereo=$bond->childNodes->item(0)->attributes->item(0)->value;
				}
				if($k<$bondArray->length-2){
						$nextTag=$bondArray->item($k+2)->nodeName;// Not very smart to proceed like this. Must be a beter way.
					}else{$nextTag=null;}
					if($tag=="bond" || $tag=="cml:bond"){// TO AVOID DOING USELESS OPERATIONS ON BONDSTEREO
						for($i=0;$i<$bond->attributes->length;$i++){
							$attribute=$bond->attributes->item($i);
							$attributeName=$attribute->name;
							$attributeValue=$attribute->value;
							switch($attributeName){
							case "id":
								$bondId=$attributeValue;
								break;
							case "atomRefs2":
								$array=split(" ",$attributeValue);
								$source=$array[0];
								$target=$array[1];
								break;
							case "order":
								$_BOND_degree=$attributeValue;
								break;
							}
						}
						$_currentObject_BOND=new Bond($bondId,$_BOND_degree,$_BOND_stereo,$_BOND_is_config_spec);
						array_push($ArrayOfBonds,$_currentObject_BOND);
						$mapOfBondAtoms[$bondId]=array($source,$target);
					}
			}
			
			/*
			 * This get all the information contained in the tag "scalar. It holds additional information about the molecule
			 * as its mass.
			 */
			foreach($scalarInformation as $info){
				$attributeLength=$info->attributes->length;
				for($attributeIndice=0;$attributeIndice<$attributeLength;$attributeIndice++){
					$attribute=$info->attributes->item($attributeIndice);
					$attributeName=$attribute->name;
					$attributeValue=$attribute->value;
					switch($attributeValue){
						case "InChI":
							$_MOLECULE_inchi=$info->childNodes->item(0)->nodeValue;
							break;
						case "ChEBI ID":
							$_MOLECULE_chebi_id=$info->childNodes->item(0)->nodeValue;
							break;
						case "Last Modified":
							$_MOLECULE_date=$info->childNodes->item(0)->nodeValue;
							break;
						case "InChiKey":
							$_MOLECULE_inchi_key=$info->childNodes->item(0)->nodeValue;
							break;
						case "Mass":
							$_MOLECULE_exact_mass=$info->childNodes->item(0)->nodeValue;
							break;
						case "FragmentMass":
							$_MOLECULE_exact_mass=$info->childNodes->item(0)->nodeValue;
							break;
						case "ChEBI Name":
							$_MOLECULE_name=$info->childNodes->item(0)->nodeValue;
							break;
					}
				}
			}
			 /*
			  * Create the molecule
			  * Put it in the database
			  * Get the Id
			  * MOdify the moleculeIdField of the atoms
			  */
//			  echo($_MOLECULE_date." ; ".$moleculeName." ; ".$_MOLECULE_inchi_key." ; ".$_MOLECULE_inchi." ; ". 
//												  $_MOLECULE_fingerprint." ; ".$_MOLECULE_chebi_id." ; ".$_MOLECULE_exact_mass);
		//	$_MOLECULE_name=isset($_MOLECULE_name) ? $_MOLECULE_name : $moleculeName;
			$_currentObject_MOLECULE=new Molecule($_MOLECULE_date, $_MOLECULE_name, $_MOLECULE_inchi_key, $_MOLECULE_inchi, 
												  $_MOLECULE_fingerprint, $_MOLECULE_chebi_id, $_MOLECULE_exact_mass);
		  	$_currentObject_MOLECULE->create();
//		  	var_dump("THe molecule has been created: ".$_MOLECULE_name." -->".$_currentObject_MOLECULE->getmoleculeID());			  	
			/*
			 * (i) Create the object atom
			 * (ii) Put it in the DB and generate its ID
			 * (iii) Create the C2DS object
			 * (iv) Put it in the DB
			 */
//			$_currentObject_ATOM=new Atom($_ATOM_symbol, $_ATOM_is_aromatic, $_ATOM_is_visible, $_ATOM_formal_charge,
//										 $_ATOM_atomic_mass, $_ATOM_signature);
//			$_currentObject_ATOM->create();
//			$_mapAtomsId[$atomId]=$_currentObject_ATOM->_atomID;
			$transitoryMapOfAtomIds=Atom::createAndReturn($ArrayOfAtoms,$_currentObject_MOLECULE->getmoleculeID());
		//	$ArrayOfAtoms=array();
			foreach($transitoryMapOfAtomIds as $innerId => $atomIdentifier){
//				var_dump($innerId."==>".$atomIdentifier."   ;   ".$mapOfCoordinates[$innerId][0]."</br>");
				$_currentObject_CS2D=new Coordinates($atomIdentifier,
													 $mapOfCoordinates[$innerId][0],
													 $mapOfCoordinates[$innerId][1]);
				array_push($ArrayOfCS2D,$_currentObject_CS2D);
			}
			Coordinates::createFromArray($ArrayOfCS2D);
	//		$mapOfCoordinates=array();
//			echo("</br></br>");
//			$_currentObject_CS2D=new Coordinates($_currentObject_ATOM->_atomID, $atomX, $atomY);
//			$_currentObject_CS2D->create();	
			  
			/*
			 * Create the BOND
			 * get the real ATOMID from the innerId
			 * Create 2 entries in BOND_ATOM
			 */
			 $transitoryMapOfBondsIds=Bond::createAndReturn($ArrayOfBonds);
			 foreach($transitoryMapOfBondsIds as $innerId => $bondIdentifier){
//			 	echo("</br></br>");
//			 	echo($innerId." ; ".$bondIdentifier."--->".$transitoryMapOfAtomIds[$mapOfBondAtoms[$innerId][0]]);
//			 	echo("</br></br>");
			 	$currentBondAtom1=new BondAtom(0,$bondIdentifier,$transitoryMapOfAtomIds[$mapOfBondAtoms[$innerId][0]]);
			 	$currentBondAtom2=new BondAtom(1,$bondIdentifier,$transitoryMapOfAtomIds[$mapOfBondAtoms[$innerId][1]]);
			 	array_push($ArrayOfBondAtom,$currentBondAtom1,$currentBondAtom2);
			 }
			 BondAtom::createFromArray($ArrayOfBondAtom);
//			$_currentObject_BOND=new Bond($_BOND_degree,$_BOND_stereo,$_BOND_is_config_spec);
//			$bondAtom1=new BondAtom(0,$_currentObject_BOND->_bondID,$mapAtomsId[$source]);
//			$bondAtom2=new BondAtom(1,$_currentObject_BOND->_bondID,$mapAtomsId[$target]);
//			$bondAtom1->create();
//			$bondAtom2->create();
		}
		
		$ArrayOfBonds=array();$transitoryMapOfBondsIds=array();$ArrayOfBondAtom=array();
		$ArrayOfAtoms=array();$transitoryMapOfAtomIds=array();$mapOfCoordinates=array();
		$ArrayOfCS2D=array();
		
	}
	
			$peakList=$srcFile->getElementsByTagName("peakList")->item(0)->childNodes;//Peaks are the same for MS and NMR
			foreach($peakList as $peak){
				$moleculeRef=null;
				$isThereAmoleculeAssignedToThePeak=($peak->childNodes->item(0)->nodeName!=null) ? true : false;
				if($isThereAmoleculeAssignedToThePeak){
					$moleculeRef=$peak->childNodes->item(0)->attributes->item(0)->value;
				}
				for($attributeIndice=0;$attributeIndice<$peak->attributes->length;$attributeIndice++){
					$attribute=$peak->attributes->item($attributeIndice);
					$attributeName=$attribute->name;
					$attributeValue=$attribute->value;
					switch($attributeName){
						case "xValue":
							$xValue=floatval(attributeValue);
							$maxPValue=($xValue>$maxPValue ? $xValue : $maxPValue);
							break;
						case "xUnits":
							$xUnits=$attributeValue;
							break;
						case "yUnits":
							$yUnits=$attributeValue;
							break;
						case "peakShape":
							$peakShape=$attributeValue;
							break;
						case "peakMultiplicity":
							$multiplicity=$attributeValue;
							break;
						case "id":
							$peakId=$attributeValue;
							break;
						case "atomRefs":
							$atomRefs=$attributeValue.split(" ");
							break;
						case "moleculeRefs" :
							$moleculeRef=$attributeValue;
							break;
						case "yValue":
							$height=$attributeValue;
							break;
						default:
							break;
					}
				}
//				var_dump($xValue." , ".$xUnits." , ".$yUnits." , ".$peakShape." , ".$height."<br/><br/>");
			 /*
			  * Everything is ready to populate the information relative to the spectrum . Just need to create  the  object and call the CRUD
			  */
			}
}

	public function startsWith($word,$string){
		return ($word==substr($string,0,strlen($word)) ? true : false);	
	}

	
}
?>
